#!/usr/bin/env python
#coding=utf8
#Author:linluxiang@gmail.com
#version:0.9.0 alpha
import os
import sys
import StringIO
import threading
import thread
import wx
import wx.stc as stc
import wx.lib.flatnotebook as fnb
import symbols
import cmm
import cmmc
import time
if wx.Platform == u'__WXMSW__':
    faces = { u'times': u'Times New Roman',
              u'mono' : u'Courier New',
              u'helv' : u'Arial',
              u'other': u'Comic Sans MS',
              u'size' : 12,
              u'size2': 10,
             }
elif wx.Platform == u'__WXMAC__':
    faces = { u'times': u'Times New Roman',
              u'mono' : u'Monaco',
              u'helv' : u'Arial',
              u'other': u'Comic Sans MS',
              u'size' : 12,
              u'size2': 10,
             }
else:
    faces = { u'times': u'Times',
              u'mono' : u'Courier',
              u'helv' : u'Helvetica',
              u'other': u'new century schoolbook',
              u'size' : 12,
              u'size2': 10,
             }

styledict={
                0: u'', 1: u'fore:#008040,back:#EAFFEA',
                2: u'fore:#008040,back:#EAFFEA',
                3: u'',
                4: u'fore:#0076AE',
                5: u'bold,fore:#004080',
                6: u'fore:#800080',
                7: u'fore:#800040',
                8: u'',
                9: u'fore:#808000',
                10: u'bold',
                11: u'',
                12: u'back:#FFD5FF',
                13: u'fore:#8000FF',
                32: u'face:%(mono)s,size:%(size)d',
                33: u'size:%(ln-size)s',
                34: u'fore:#0000FF,back:#FFFFB9,bold',
                35: u'fore:#FF0000,back:#FFFFB9,bold',
                36: u'',
                37: u'',
                -2: u'',
                -3: u'fore:#C4C4FF',
                -1: u''}
commondefs={u'size': 12, u'plaintext-size': 12, u'mono': u'Courier', u'ln2-size': 9, u'ln-font': u'Helvetica', u'backcol': u'#FFFFFF', u'ln-size': 10}



ID_FRAME1 = wx.NewId()
ID_STYLEDTEXTCTRL = wx.NewId()
ID_TOOLBAR= wx.NewId()
ID_BOOK  =  wx.NewId()
ID_NEW   =  wx.NewId()  
ID_OPEN  =  wx.NewId()  
ID_SAVE  =  wx.NewId()  
ID_SAVEAS = wx.NewId()  
ID_EXIT  =  wx.NewId()
ID_UNDO  =  wx.NewId()
ID_REDO  =  wx.NewId()
ID_CUT   =  wx.NewId()  
ID_COPY  =  wx.NewId()  
ID_PASTE =  wx.NewId()  
ID_SELECT = wx.NewId()  
ID_OUTPUT =  wx.NewId() 
ID_OUTPUT_BOOK=wx.NewId()
ID_COMPILE= wx.NewId()
ID_RUN   =  wx.NewId()
ID_ABOUT =  wx.NewId()
ID_TREE  =  wx.NewId()

cmmInLock=threading.Lock()
cmmOutLock=threading.Lock()


class MyThread(threading.Thread):
    def __init__(self,func,argv):
        threading.Thread.__init__(self)
        self.func=func
        self.argv=argv
    def run(self):
        self.func(self.argv)

class CmmStyledTextCtrl(stc.StyledTextCtrl):
    def __init__(self, parent,id,pos=wx.DefaultPosition,size=wx.DefaultSize,style=0):
        stc.StyledTextCtrl.__init__(self,parent=parent,id=id,pos=pos,size=size,style=style)
        #设置是否显示水平滚动条
        self.SetUseHorizontalScrollBar(True)
        #设置边界
        self.SetEdgeMode(stc.STC_EDGE_LINE)
        self.SetEdgeColumn(200)
        #设置做边距以及行号
        self.SetMargins(0,0)
        self.SetMarginType(0, stc.STC_MARGIN_NUMBER)
        self.SetMarginWidth(0, 25)
        #设置tab
        self.SetUseTabs(False)
        self.SetTabWidth(4)
        self.SetIndentationGuides(True)
        #设置语法高亮
        #wx.MessageBox(str(stc.STC_STYLE_DEFAULT))
        self.StyleResetDefault()
        self.ClearDocumentStyle()
        self.SetLexer(stc.STC_LEX_CPP)
        self.SetKeyWords(0, " ".join(symbols.Keyword))
        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,styledict[stc.STC_STYLE_DEFAULT] % commondefs)

        self.StyleClearAll()
        for k,v in styledict.items():
            if k >= 0:
                #print stc.STC_C_WORD
                #print k
                self.StyleSetSpec(k,v%commondefs)
            #elif num == -3:
        self.SetEdgeColour((196, 196, 255, 255))
        self.SetCaretForeground(u"BLACK")





class MyMenuBar(wx.MenuBar):
    def __init__(self,pnt):
        wx.MenuBar.__init__(self)
        #创建菜单项目
        file=wx.Menu()
        edit=wx.Menu()
        program=wx.Menu()
        help=wx.Menu()
        #设置菜单，文件
        file.Append(ID_NEW,u'新建(&N)\tCtrl+N',u'创建新文件')
        pnt.Bind(wx.EVT_MENU,pnt.OnNewFile,id=ID_NEW)

        file.Append(ID_OPEN,u'打开(&O)\tCtrl+O',u'打开一个文件')
        pnt.Bind(wx.EVT_MENU,pnt.OnOpen,id=ID_OPEN)

        file.Append(ID_SAVE,u'保存(&S)\tCtrl+S',u'保存文件')
        pnt.Bind(wx.EVT_MENU,pnt.OnSave,id=ID_SAVE)

        file.Append(ID_SAVEAS,u'另存为(&A)\tCtrl+Shift+S',u'文件另存为')
        pnt.Bind(wx.EVT_MENU,pnt.OnSaveAs,id=ID_SAVEAS)
        
        file.AppendSeparator()

        file.Append(ID_EXIT,u'退出(&Q)\tCtrl+Q',u'关闭程序')
        pnt.Bind(wx.EVT_MENU,pnt.OnExit,id=ID_EXIT)

        self.Append(file,u'文件(&F)')
        
        #设置菜单，编辑
        edit.Append(ID_UNDO,u'撤销(&U)\tCtrl+Z',u'撤销一次操作')
        pnt.Bind(wx.EVT_MENU,pnt.OnUndo,id=ID_UNDO)

        edit.Append(ID_REDO,u'重做(&R)\tCtrl+Shift+Z',u'重复一次操作')
        pnt.Bind(wx.EVT_MENU,pnt.OnRedo,id=ID_REDO)
        
        edit.AppendSeparator()
        
        edit.Append(ID_CUT,u'剪切(&T)\tCtrl+X',u'剪切选中内容')
        pnt.Bind(wx.EVT_MENU,pnt.OnCut,id=ID_CUT)

        edit.Append(ID_COPY,u'复制(&C)\tCtrl+C',u'复制选中内容')
        pnt.Bind(wx.EVT_MENU,pnt.OnCopy,id=ID_COPY)
        
        edit.Append(ID_PASTE,u'粘贴(&P)\tCtrl+V',u'粘贴内容')
        pnt.Bind(wx.EVT_MENU,pnt.OnPaste,id=ID_PASTE)
        
        file.AppendSeparator()

        edit.Append(ID_SELECT,u'全部选中(&A)\tCtrl+A',u'全部选中')
        pnt.Bind(wx.EVT_MENU,pnt.OnSelectAll,id=ID_SELECT)
        
        self.Append(edit,u'编辑(&E)')

        #设置菜单，程序
        program.Append(ID_COMPILE,u'编译(&C)\tF5',u'编译程序')
        pnt.Bind(wx.EVT_MENU,pnt.OnCompile,id=ID_COMPILE)
        
        program.Append(ID_RUN,u'运行(&R)\tF6',u'运行程序')
        pnt.Bind(wx.EVT_MENU,pnt.OnRun,id=ID_RUN)
        
        self.Append(program,u'程序(&P)')
        #设置菜单，帮助
        help.Append(ID_ABOUT,u'关于(&A)',u'关于本程序')
        pnt.Bind(wx.EVT_MENU,pnt.OnAbout,id=ID_ABOUT)
        
        self.Append(help,u'帮助(&H)')

       
class Frame1(wx.Frame):
    
    #--------------PublicBlock----------

    def __init__(self, parent):
        wx.Frame.__init__(self, id=ID_FRAME1,parent=parent,
              style=wx.DEFAULT_FRAME_STYLE, title=u'Turbo Cmm')
        self._init_utils(parent)
        sizer=wx.BoxSizer(wx.VERTICAL)
        sizer2=wx.BoxSizer(wx.HORIZONTAL)
        #sizer2.Add(self.treeBook,1,wx.EXPAND)
        sizer2.Add(self.book,4,wx.EXPAND)
        sizer.Add(sizer2,6,wx.EXPAND)
        sizer.Add(self.outputBook,1,wx.EXPAND)
        self.SetSizerAndFit(sizer)

    #----------------CtrlBlock---------------

    #def _init_ctrls(self, prnt): 
    #    self.stc =CmmStyledTextCtrl(id=ID_STYLEDTEXTCTRL, parent=self)
        
    #---------MenuBlock-------------
    def _init_utils(self,prnt):
        #创建菜单
        menuBar=MyMenuBar(self)
        self.SetMenuBar(menuBar)
        #创建工具条
        tsize=(24,24)
        new_bmp =  wx.Bitmap('img/new.png')
        open_bmp = wx.Bitmap('img/open.png')
        save_bmp = wx.Bitmap('img/save.png')
        cut_bmp = wx.Bitmap('img/cut.png')
        copy_bmp = wx.Bitmap('img/copy.png')
        paste_bmp= wx.Bitmap('img/paste.png')
        undo_bmp = wx.Bitmap('img/undo.png')
        redo_bmp = wx.Bitmap('img/redo.png')
        compile_bmp = wx.Bitmap('img/compile.png')
        run_bmp = wx.Bitmap('img/run.png')
# wx.ART_TIP
        toolbar=self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER  | wx.TB_FLAT | wx.TB_FLAT)
        toolbar.SetToolBitmapSize(tsize)
        toolbar.AddLabelTool(ID_NEW, u'新建文件', new_bmp,shortHelp=u'新建文件',longHelp=u'创建一个新的文件')  
        toolbar.AddLabelTool(ID_OPEN, u'打开文件', open_bmp,shortHelp=u'打开文件',longHelp=u'打开一个已有的文件')  
        toolbar.AddLabelTool(ID_SAVE, u'保存文件', save_bmp,shortHelp=u'保存文件',longHelp=u'保存当前标签的文件')
        toolbar.AddSeparator()
        toolbar.AddLabelTool(ID_UNDO, u'撤销', undo_bmp,shortHelp=u'撤销',longHelp=u'撤销一次操作')
        toolbar.AddLabelTool(ID_REDO, u'重复', redo_bmp,shortHelp=u'重复',longHelp=u'重复一次操作')
        toolbar.AddSeparator()
        toolbar.AddLabelTool(ID_CUT, u'剪切', cut_bmp,shortHelp=u'剪切',longHelp=u'剪切选中内容')
        toolbar.AddLabelTool(ID_COPY, u'复制', copy_bmp,shortHelp=u'复制',longHelp=u'复制选中内容')
        toolbar.AddLabelTool(ID_PASTE, u'粘贴', paste_bmp,shortHelp=u'粘贴',longHelp=u'粘贴剪切板内容')
        toolbar.AddSeparator()
        toolbar.AddLabelTool(ID_COMPILE, u'编译', compile_bmp,shortHelp=u'编译',longHelp=u'编译当前程序')
        toolbar.AddLabelTool(ID_RUN, u'运行', run_bmp,shortHelp=u'运行',longHelp=u'运行当前程序')

        

        self.toolbar=toolbar
        self.toolbar.Realize()
        #创建状态栏
        self.CreateStatusBar()
        
        #创建选择栏
        book=fnb.FlatNotebook(self,ID_BOOK,style=fnb.FNB_VC8
                | fnb.FNB_X_ON_TAB
                | fnb.FNB_NO_X_BUTTON
                | fnb.FNB_NO_NAV_BUTTONS)
        
        self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
        self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
        self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnPageClosing)

        self.Bind(stc.EVT_STC_MODIFIED, self.OnModified)
        self.book=book
        self.__currentPage=0
        self.__buffer={}
        self.__pageamount=0

        
        #创建输出栏
        outputBook=fnb.FlatNotebook(self,ID_OUTPUT_BOOK,style=fnb.FNB_NO_X_BUTTON
                | fnb.FNB_NO_NAV_BUTTONS)
        outputPanel=wx.Panel(outputBook)

        sizerOutput=wx.BoxSizer(wx.HORIZONTAL)
        output=wx.TextCtrl(outputPanel,ID_OUTPUT,style=wx.TE_MULTILINE | wx.TE_READONLY)
        sizerOutput.Add(output,1,flag=wx.EXPAND)
        
        outputPanel.SetSizerAndFit(sizerOutput)
        outputBook.AddPage(outputPanel,u'输出')
        self.output=output
        self.outputBook=outputBook
        
      

    #--------Event------------------
    def OnNewFile(self,event):
        #程序先执行OnNewFile，在执行CreatePage，再执行Changing，再执行Changed
        panel=self.CreatePage()
        self.book.AddPage(panel,u'NoName',True)

        #sys.stdin.readline();

    def CreatePage(self):
        panel=wx.Panel(self.book)
        self.Freeze()
        sizer=wx.BoxSizer(wx.HORIZONTAL)
        text=CmmStyledTextCtrl(parent=panel,id=ID_STYLEDTEXTCTRL)
        sizer.Add(text,1,flag=wx.EXPAND)
        panel.SetSizer(sizer)
        self.__buffer[self.__pageamount]=text
        buffer=self.__buffer[self.__pageamount]
        self.__pageamount+=1
        buffer.filename=u'NoName'
        buffer.userIn=StringIO.StringIO()
        buffer.userOut=StringIO.StringIO()
        buffer.ready=threading.Lock()
        buffer.cmmguiin=threading.Lock()
        buffer.complete=False
        buffer.SetSavePoint()
        self.Thaw()
        return panel
    def OnOpen(self,event):
        wildcard = u"Cmm source (*.cmm)|*.cmm|" \
                    u"All files (*.*)|*.*"

        dlg=wx.FileDialog(  
            self,message=u'选择一个文件', defaultDir=os.getcwd(),  
            defaultFile="", wildcard=wildcard,  
            style=wx.OPEN|wx.CHANGE_DIR  
            )
        
        if dlg.ShowModal()==wx.ID_OK:
            path=dlg.GetPath()
            if path:
                panel=self.CreatePage()

                try:
                    self.book.AddPage(panel,dlg.GetFilename(),True)
                    
                    if self.__buffer.has_key(self.__currentPage):
                        buffer=self.__buffer[self.__currentPage]
                        filename=dlg.GetFilename()
                        buffer.filename=filename
                        buffer.path=path
                        buffer.LoadFile(path)
                        self.book.SetPageText(self.__currentPage,filename)
                        
                        buffer.SetSavePoint()
                except Exception,e:
                    print e
                    
        dlg.Destroy()
    def OnSave(self,event):
        wildcard = u"Cmm source (*.cmm)|*.cmm|" \
                    u"All files (*.*)|*.*"
        if self.__buffer.has_key(self.__currentPage):
            buffer=self.__buffer[self.__currentPage]
            filename=buffer.filename
            if hasattr(buffer,"path"):
                path=buffer.path
            if filename!=u'NoName':
                buffer.SaveFile(path)
                self.book.SetPageText(self.__currentPage,filename)
                buffer.modTimes=0
                buffer.SetSavePoint()
            else:
                dlg=wx.FileDialog(self,message=u'保存文件...', defaultDir=os.getcwd(),  
                    defaultFile=u"new.cmm", wildcard=wildcard,  
                    style=wx.SAVE|wx.CHANGE_DIR)
                if dlg.ShowModal()==wx.ID_OK:
                    filename=dlg.GetFilename()
                    path=dlg.GetPath()
                    f=open(path,u'w')
                    f.write(buffer.GetTextUTF8())
                    f.close()
                    self.book.SetPageText(self.__currentPage,filename)
                    buffer.filename=filename
                    buffer.path=path
                    buffer.modTimes=0
                    buffer.SetSavePoint()

                dlg.Destroy()


    def OnSaveAs(self,event):
       
        wildcard = u"Cmm source (*.cmm)|*.cmm|" \
                    u"All files (*.*)|*.*"
        if self.__buffer.has_key(self.__currentPage):
            buffer=self.__buffer[self.__currentPage]
            filename=buffer.filename
            path=buffer.path
    
            dlg=wx.FileDialog(self,message=u'文件令存为...', defaultDir=os.getcwd(),  
                defaultFile=u"new.cmm", wildcard=wildcard,  
                style=wx.SAVE|wx.CHANGE_DIR)
            if dlg.ShowModal()==wx.ID_OK:
                filename=dlg.GetFilename()
                path=dlg.GetPath()
                f=open(path,u'w')
                f.write(buffer.GetTextUTF8())
                f.close()
                self.book.SetPageText(self.__currentPage,filename)
                buffer.filename=filename
                buffer.path=path
                buffer.modTimes=0
                buffer.SetSavePoint()
     
            dlg.Destroy()
    def OnExit(self,event):

        self.Close(True)
        sys.exit()
    def OnUndo(self,event):
        buffer=self.__buffer[self.__currentPage]
        buffer.Undo()

    def OnRedo(self,event):
        buffer=self.__buffer[self.__currentPage]
        buffer.Redo()

    def OnCut(self,event):
        buffer=self.__buffer[self.__currentPage]
        buffer.Cut()
        
    def OnCopy(self,event):
        buffer=self.__buffer[self.__currentPage]
        buffer.Copy()
    def OnPaste(self,event):
        buffer=self.__buffer[self.__currentPage]
        buffer.Paste()
    def OnSelectAll(self,event):
        buffer=self.__buffer[self.__currentPage]
        buffer.SelectAll()

    def OnCompile(self,event):
        if self.__buffer.has_key(self.__currentPage):
            buffer=self.__buffer[self.__currentPage]
            self.OnSave(event)
            if hasattr(buffer,"path"):
                cmmc.userOut=buffer.userOut
                cmmcCompiler=MyThread(cmmc.Compile,buffer.path)
                cmmcCompiler.start()
                while cmmcCompiler.isAlive():
                    pass
                self.output.Clear()
                self.output.AppendText(buffer.userOut.getvalue()) 
                buffer.userOut.close()
                buffer.userOut=StringIO.StringIO()

        event.Skip()
    def OnRun(self,event):
        if self.__buffer.has_key(self.__currentPage):
            buffer=self.__buffer[self.__currentPage]
            buffer.complete=False
            buffer.ready.acquire()
            buffer.cmmguiin.acquire()
            path=buffer.path+'c'
            cmm.userIn=buffer.userIn
            cmm.userOut=buffer.userOut
            cmmRunner=MyThread(cmm.Run,path)
            cmmRunner.start()
            self.output.Clear()
            text=buffer.userOut.getvalue()
            while cmm.complete==False:
                if cmm.ready==True:
                    dialog = wx.TextEntryDialog(None,
                        u'Input value',
                        u"Input", "", style=wx.OK|wx.CANCEL)
                    if dialog.ShowModal() == wx.ID_OK:
                        a=dialog.GetValue()
                        cmm.guiin.append(a)
                        cmm.ready=False
                    dialog.Destroy()

            self.output.AppendText(buffer.userOut.getvalue())
            text=buffer.userOut.getvalue()
            buffer.userOut.close()
            buffer.userOut=StringIO.StringIO()
            buffer.cmmguiin.release()
            buffer.ready.release()
        event.Skip()
            

    def OnAbout(self,event):
        info = wx.AboutDialogInfo()  
        info.Name = u'Turbo CMM'
        info.Version = u'1.0.0 beta'
        info.Copyright = u'(C) 2008 linluxiang@gmail.com'
        info.Description=u'本程序是基于Python 2.5.2，wxPython 2.8.9.1完成。为开源软件，如想要源代码可以发送邮件向作者索取。'
        info.Developers=[u'林路翔  linluxiang@gmail.com']
        wx.AboutBox(info)
    
    def OnPageChanged(self, event):
        self.__currentPage=event.GetSelection()
        event.Skip()
    def OnPageChanging(self,event):
        event.Skip()
    def OnPageClosing(self,event):
        wildcard = u"Cmm source (*.cmm)|*.cmm|" \
                    u"All files (*.*)|*.*"
        if self.__buffer.has_key(self.__currentPage):
            buffer=self.__buffer[self.__currentPage]
            if buffer:
                
                if buffer.GetModify():
                    dlg = wx.MessageDialog(None, u"该文件已被修改，是否保存？",
                                          u'提示',wx.YES_NO | wx.ICON_QUESTION)
                    if dlg.ShowModal()==wx.ID_YES:
                        filename=buffer.filename
                        if filename==u'NoName':filename=u'new.cmm'
                        dlg=wx.FileDialog(self,message=u'保存文件...', defaultDir=os.getcwd(),  
                            defaultFile=filename, wildcard=wildcard,  
                            style=wx.SAVE|wx.CHANGE_DIR)
                        if dlg.ShowModal()==wx.ID_OK:
                            filename=dlg.GetFilename()
                            path=dlg.GetPath()
                            f=open(path,u'w')
                            f.write(buffer.GetTextUTF8())
                            f.close()
                del self.__buffer[self.__currentPage]
                self.__pageamount-=1
            
        event.Skip()

    def OnModified(self,event):
        buffer=self.__buffer[self.__currentPage]
        if buffer.GetModify():
            filename=''.join([buffer.filename,u'[+]'])
            self.book.SetPageText(int(self.__currentPage),filename)
        else:
            self.book.SetPageText(int(self.__currentPage),buffer.filename)

class TCMMApp(wx.App):
    def OnInit(self):
        self.main = Frame1(parent=None)
        self.main.Maximize()
        self.main.Show()

        icon=wx.EmptyIcon()  
        icon.LoadFile("img/TCMM.png",wx.BITMAP_TYPE_PNG) 
        self.main.SetIcon(icon)
        self.SetTopWindow(self.main)
        return True

def main():
    application = TCMMApp(redirect=False)
    application.MainLoop()

if __name__ == u'__main__':
    main()
